home *** CD-ROM | disk | FTP | other *** search
/ Gold Medal Software 3 / Gold Medal Software - Volume 3 (Gold Medal) (1994).iso / bbsutils / smb_110a.arj / SMBUTIL.C < prev    next >
C/C++ Source or Header  |  1994-03-28  |  33KB  |  1,291 lines

  1. /* SMBUTIL.C */
  2.  
  3. /* Synchronet Message Base Utility */
  4.  
  5. #define SMBUTIL_VER "1.10"
  6.  
  7. #include "smblib.h"
  8. #include "smbutil.h"
  9. #include "crc32.h"
  10.  
  11. /********************/
  12. /* Global variables */
  13. /********************/
  14.  
  15. ulong mode=0L;
  16. ushort tzone=PST;
  17. char filein[128];
  18. char attach[128];
  19.  
  20. /************************/
  21. /* Program usage/syntax */
  22. /************************/
  23.  
  24. char *usage=
  25. "usage: smbutil [/opts] cmd <filespec.SHD>\n"
  26. "\n"
  27. "cmd:\n"
  28. "       l[n] = list msgs starting at number n\n"
  29. "       r[n] = read msgs starting at number n\n"
  30. "       v[n] = view msg headers starting at number n\n"
  31. "       k[n] = kill (delete) n msgs\n"
  32. "       i<f> = import from text file f\n"
  33. "       s    = display msg base status\n"
  34. "       c    = change msg base status\n"
  35. "       m    = maintain msg base - delete old msgs and msgs over max\n"
  36. "       p    = pack msg base\n"
  37. "opts:\n"
  38. "       a    = always pack msg base (disable compression analysis)\n"
  39. "       f    = fast msg creation mode\n"
  40. "       d    = disable duplicate message checking\n"
  41. "       z[n] = set time zone (n=min +/- from UT or 'EST','EDT','CST',etc)\n"
  42. ;
  43.  
  44. /****************************************************************************/
  45. /* Checks the disk drive for the existence of a file. Returns 1 if it       */
  46. /* exists, 0 if it doesn't.                                                 */
  47. /****************************************************************************/
  48. char fexist(char *filespec)
  49. {
  50.     struct ffblk f;
  51.  
  52. if(findfirst(filespec,&f,0)==0)
  53.     return(1);
  54. return(0);
  55. }
  56.  
  57. /****************************************************************************/
  58. /* Returns the length of the file in 'filespec'                             */
  59. /****************************************************************************/
  60. long flength(char *filespec)
  61. {
  62.     struct ffblk f;
  63.  
  64. if(findfirst(filespec,&f,0)==0)
  65.     return(f.ff_fsize);
  66. return(-1L);
  67. }
  68.  
  69. /****************************************************************************/
  70. /* Updates 16-bit "rcrc" with character 'ch'                                */
  71. /****************************************************************************/
  72. void ucrc16(uchar ch, ushort *rcrc) {
  73.     ushort i, cy;
  74.     uchar nch=ch;
  75.  
  76. for (i=0; i<8; i++) {
  77.     cy=*rcrc & 0x8000;
  78.     *rcrc<<=1;
  79.     if (nch & 0x80) *rcrc |= 1;
  80.     nch<<=1;
  81.     if (cy) *rcrc ^= 0x1021; }
  82. }
  83.  
  84. /****************************************************************************/
  85. /* Returns 16-crc of string (not counting terminating NULL)                 */
  86. /****************************************************************************/
  87. ushort crc16(char *str)
  88. {
  89.     int     i=0;
  90.     ushort    crc=0;
  91.  
  92. ucrc16(0,&crc);
  93. while(str[i])
  94.     ucrc16(str[i++],&crc);
  95. ucrc16(0,&crc);
  96. ucrc16(0,&crc);
  97. return(crc);
  98. }
  99.  
  100. /****************************************************************************/
  101. /* Adds a new message to the message base                                    */
  102. /****************************************************************************/
  103. void postmsg(smbstatus_t status)
  104. {
  105.     char    str[128],buf[SDT_BLOCK_LEN];
  106.     ushort    xlat;
  107.     int     i,j,k,file;
  108.     long    length;
  109.     ulong    offset,crc=0xffffffffUL;
  110.     FILE    *instream;
  111.     smbmsg_t    msg;
  112.  
  113. if(!filelength(fileno(shd_fp)))
  114.     smb_create(2000,2000,0,10);
  115. length=flength(filein);
  116. if(length<1L) {
  117.     printf("Invalid file size for '%s'\n",filein);
  118.     exit(1); }
  119. length+=2;    /* for translation string */
  120. i=smb_open_da(10);
  121. if(i) {
  122.     printf("smb_open_da returned %d\n",i);
  123.     exit(1); }
  124. if(mode&FAST)
  125.     offset=smb_fallocdat(length,1);
  126. else
  127.     offset=smb_allocdat(length,1);
  128. fclose(sda_fp);
  129. if((file=open(filein,O_RDONLY|O_BINARY))==-1
  130.     || (instream=fdopen(file,"rb"))==NULL) {
  131.     printf("Error opening %s for read\n",filein);
  132.     smb_freemsgdat(offset,length,1);
  133.     exit(1); }
  134. setvbuf(instream,NULL,_IOFBF,32*1024);
  135. fseek(sdt_fp,offset,SEEK_SET);
  136. xlat=XLAT_NONE;
  137. fwrite(&xlat,2,1,sdt_fp);
  138. k=SDT_BLOCK_LEN-2;
  139. while(!feof(instream)) {
  140.     memset(buf,NULL,k);
  141.     j=fread(buf,1,k,instream);
  142.     if(!(mode&NOCRC)) {
  143.         for(i=0;i<j;i++)
  144.             crc=ucrc32(buf[i],crc); }
  145.     fwrite(buf,k,1,sdt_fp);
  146.     k=SDT_BLOCK_LEN; }
  147. fclose(instream);
  148. crc=~crc;
  149.  
  150. memset(&msg,0,sizeof(smbmsg_t));
  151. memcpy(msg.hdr.id,"SHD\x1a",4);
  152. msg.hdr.version=SMB_VERSION;
  153. msg.hdr.when_written.time=time(NULL);
  154. msg.hdr.when_written.zone=tzone;
  155.  
  156. if(!(mode&NOCRC)) {
  157.     i=smb_addcrc(status.max_crcs,crc,10);
  158.     if(i) {
  159.         printf("smb_addcrc returned %d\n",i);
  160.         smb_freemsgdat(offset,length,1);
  161.         exit(1); } }
  162.  
  163. msg.hdr.offset=offset;
  164.  
  165. printf("To: ");
  166. gets(str);
  167. i=smb_hfield(&msg,RECIPIENT,strlen(str),str);
  168. if(i) {
  169.     printf("smb_hfield returned %d\n",i);
  170.     smb_freemsgdat(offset,length,1);
  171.     exit(1); }
  172. strlwr(str);
  173. msg.idx.to=crc16(str);
  174.  
  175. printf("From: ");
  176. gets(str);
  177. i=smb_hfield(&msg,SENDER,strlen(str),str);
  178. if(i) {
  179.     printf("smb_hfield returned %d\n",i);
  180.     smb_freemsgdat(offset,length,1);
  181.     exit(1); }
  182. strlwr(str);
  183. msg.idx.from=crc16(str);
  184.  
  185. printf("Subj: ");
  186. gets(str);
  187. i=smb_hfield(&msg,SUBJECT,strlen(str),str);
  188. if(i) {
  189.     printf("smb_hfield returned %d\n",i);
  190.     smb_freemsgdat(offset,length,1);
  191.     exit(1); }
  192. strlwr(str);
  193. msg.idx.subj=crc16(str);
  194.  
  195. i=smb_dfield(&msg,TEXT_BODY,length);
  196. if(i) {
  197.     printf("smb_dfield returned %d\n",i);
  198.     smb_freemsgdat(offset,length,1);
  199.     exit(1); }
  200.  
  201. i=smb_addmsghdr(&msg,&status,mode&FAST,10);
  202.  
  203. if(i) {
  204.     printf("smb_addmsghdr returned %d\n",i);
  205.     smb_freemsgdat(offset,length,1);
  206.     exit(1); }
  207. smb_freemsgmem(msg);
  208.  
  209. }
  210.  
  211. /****************************************************************************/
  212. /* Shows the message base header                                            */
  213. /****************************************************************************/
  214. void showstatus()
  215. {
  216.     int i;
  217.     smbstatus_t status;
  218.  
  219. i=smb_locksmbhdr(10);
  220. if(i) {
  221.     printf("smb_locksmbhdr returned %d\n",i);
  222.     return; }
  223. i=smb_getstatus(&status);
  224. smb_unlocksmbhdr();
  225. if(i) {
  226.     printf("smb_getstatus returned %d\n",i);
  227.     return; }
  228. printf("last_msg        =%lu\n"
  229.        "total_msgs      =%lu\n"
  230.        "header_offset   =%lu\n"
  231.        "max_crcs        =%lu\n"
  232.        "max_msgs        =%lu\n"
  233.        "max_age         =%u\n"
  234.        "reserved        =%04Xh\n"
  235.        ,status.last_msg
  236.        ,status.total_msgs
  237.        ,status.header_offset
  238.        ,status.max_crcs
  239.        ,status.max_msgs
  240.        ,status.max_age
  241.        ,status.reserved
  242.        );
  243. }
  244.  
  245. /****************************************************************************/
  246. /* Configure message base header                                            */
  247. /****************************************************************************/
  248. void config()
  249. {
  250.     char max_msgs[128],max_crcs[128],max_age[128];
  251.     int i;
  252.     smbstatus_t status;
  253.  
  254. i=smb_locksmbhdr(10);
  255. if(i) {
  256.     printf("smb_locksmbhdr returned %d\n",i);
  257.     return; }
  258. i=smb_getstatus(&status);
  259. smb_unlocksmbhdr();
  260. if(i) {
  261.     printf("smb_getstatus returned %d\n",i);
  262.     return; }
  263. printf("Max msgs =%-5lu  New value (CR=No Change): ",status.max_msgs);
  264. gets(max_msgs);
  265. printf("Max crcs =%-5lu  New value (CR=No Change): ",status.max_crcs);
  266. gets(max_crcs);
  267. printf("Max age  =%-5u  New value (CR=No Change): ",status.max_age);
  268. gets(max_age);
  269. i=smb_locksmbhdr(10);
  270. if(i) {
  271.     printf("smb_locksmbhdr returned %d\n",i);
  272.     return; }
  273. i=smb_getstatus(&status);
  274. if(i) {
  275.     printf("smb_getstatus returned %d\n",i);
  276.     smb_unlocksmbhdr();
  277.     return; }
  278. if(isdigit(max_msgs[0]))
  279.     status.max_msgs=atol(max_msgs);
  280. if(isdigit(max_crcs[0]))
  281.     status.max_crcs=atol(max_crcs);
  282. if(isdigit(max_age[0]))
  283.     status.max_age=atoi(max_age);
  284. i=smb_putstatus(status);
  285. smb_unlocksmbhdr();
  286. if(i)
  287.     printf("smb_putstatus returned %d\n",i);
  288. }
  289.  
  290. /****************************************************************************/
  291. /* Lists messages' to, from, and subject                                    */
  292. /****************************************************************************/
  293. void listmsgs(ulong start, ulong count)
  294. {
  295.     int i;
  296.     ulong l=0;
  297.     smbmsg_t msg;
  298.     idxrec_t idxrec;
  299.  
  300. if(!start)
  301.     start=1;
  302. fseek(sid_fp,(start-1L)*sizeof(idxrec_t),SEEK_SET);
  303. while(l<count) {
  304.     if(!fread(&msg.idx,1,sizeof(idxrec_t),sid_fp))
  305.         break;
  306.     i=smb_lockmsghdr(msg,10);
  307.     if(i) {
  308.         printf("smb_lockmsghdr returned %d\n",i);
  309.         break; }
  310.     i=smb_getmsghdr(&msg);
  311.     smb_unlockmsghdr(msg);
  312.     if(i) {
  313.         printf("smb_getmsghdr returned %d\n",i);
  314.         break; }
  315.     printf("%4lu %-25.25s %-25.25s %.20s\n"
  316.         ,msg.hdr.number,msg.from,msg.to,msg.subj);
  317.     smb_freemsgmem(msg);
  318.     l++; }
  319. }
  320.  
  321. /****************************************************************************/
  322. /* Returns an ASCII string for FidoNet address 'addr'                       */
  323. /****************************************************************************/
  324. char *faddrtoa(fidoaddr_t addr)
  325. {
  326.     static char str[25];
  327.     char point[25];
  328.  
  329. sprintf(str,"%u:%u/%u",addr.zone,addr.net,addr.node);
  330. if(addr.point) {
  331.     sprintf(point,".%u",addr.point);
  332.     strcat(str,point); }
  333. return(str);
  334. }
  335.  
  336. char *binstr(uchar *buf, ushort length)
  337. {
  338.     static char str[128];
  339.     char tmp[128];
  340.     int i;
  341.  
  342. str[0]=0;
  343. for(i=0;i<length;i++)
  344.     if(buf[i] && (buf[i]<SP || buf[i]>=0x7f))
  345.         break;
  346. if(i==length)        /* not binary */
  347.     return(buf);
  348. for(i=0;i<length;i++) {
  349.     sprintf(tmp,"%02X ",buf[i]);
  350.     strcat(str,tmp); }
  351. return(str);
  352. }
  353.  
  354. /****************************************************************************/
  355. /* Converts when_t.zone into ASCII format                                    */
  356. /****************************************************************************/
  357. char *zonestr(short zone)
  358. {
  359.     static char str[32];
  360.  
  361. switch(zone) {
  362.     case 0:     return("UT");
  363.     case AST:    return("AST");
  364.     case EST:    return("EST");
  365.     case CST:    return("CST");
  366.     case MST:    return("MST");
  367.     case PST:    return("PST");
  368.     case YST:    return("YST");
  369.     case HST:    return("HST");
  370.     case BST:    return("BST");
  371.     case ADT:    return("ADT");
  372.     case EDT:    return("EDT");
  373.     case CDT:    return("CDT");
  374.     case MDT:    return("MDT");
  375.     case PDT:    return("PDT");
  376.     case YDT:    return("YDT");
  377.     case HDT:    return("HDT");
  378.     case BDT:    return("BDT");
  379.     case MID:    return("MID");
  380.     case VAN:    return("VAN");
  381.     case EDM:    return("EDM");
  382.     case WIN:    return("WIN");
  383.     case BOG:    return("BOG");
  384.     case CAR:    return("CAR");
  385.     case RIO:    return("RIO");
  386.     case FER:    return("FER");
  387.     case AZO:    return("AZO");
  388.     case LON:    return("LON");
  389.     case BER:    return("BER");
  390.     case ATH:    return("ATH");
  391.     case MOS:    return("MOS");
  392.     case DUB:    return("DUB");
  393.     case KAB:    return("KAB");
  394.     case KAR:    return("KAR");
  395.     case BOM:    return("BOM");
  396.     case KAT:    return("KAT");
  397.     case DHA:    return("DHA");
  398.     case BAN:    return("BAN");
  399.     case HON:    return("HON");
  400.     case TOK:    return("TOK");
  401.     case SYD:    return("SYD");
  402.     case NOU:    return("NOU");
  403.     case WEL:    return("WEL");
  404.     }
  405.  
  406. sprintf(str,"%02d:%02d",zone/60,zone<0 ? (-zone)%60 : zone%60);
  407. return(str);
  408. }
  409.              
  410.  
  411. /****************************************************************************/
  412. /* Displays message header information                                        */
  413. /****************************************************************************/
  414. void viewmsgs(ulong start, ulong count)
  415. {
  416.     char when_written[128]
  417.         ,when_imported[128];
  418.     int i;
  419.     ulong l=0;
  420.     smbmsg_t msg;
  421.     idxrec_t idxrec;
  422.  
  423. if(!start)
  424.     start=1;
  425. fseek(sid_fp,(start-1L)*sizeof(idxrec_t),SEEK_SET);
  426. while(l<count) {
  427.     if(!fread(&msg.idx,1,sizeof(idxrec_t),sid_fp))
  428.         break;
  429.     i=smb_lockmsghdr(msg,10);
  430.     if(i) {
  431.         printf("smb_lockmsghdr returned %d\n",i);
  432.         break; }
  433.     i=smb_getmsghdr(&msg);
  434.     smb_unlockmsghdr(msg);
  435.     if(i) {
  436.         printf("smb_getmsghdr returned %d\n",i);
  437.         break; }
  438.  
  439.     sprintf(when_written,"%.24s %s"
  440.         ,ctime((time_t *)&msg.hdr.when_written.time)
  441.         ,zonestr(msg.hdr.when_written.zone));
  442.     sprintf(when_imported,"%.24s %s"
  443.         ,ctime((time_t *)&msg.hdr.when_imported.time)
  444.         ,zonestr(msg.hdr.when_imported.zone));
  445.  
  446.     printf( "%-20.20s %s\n"
  447.             "%-20.20s %s\n"
  448.             "%-20.20s %s\n"
  449.             "%-20.20s %04Xh\n"
  450.             "%-20.20s %04Xh\n"
  451.             "%-20.20s %u\n"
  452.             "%-20.20s %04Xh\n"
  453.             "%-20.20s %08lXh\n"
  454.             "%-20.20s %08lXh\n"
  455.             "%-20.20s %s\n"
  456.             "%-20.20s %s\n"
  457.             "%-20.20s %ld\n"
  458.             "%-20.20s %ld\n"
  459.             "%-20.20s %ld\n"
  460.             "%-20.20s %ld\n"
  461.             "%-20.20s %s\n"
  462.             "%-20.20s %ld\n"
  463.             "%-20.20s %u\n",
  464.  
  465.         "subj",
  466.         msg.subj,
  467.  
  468.         "from",
  469.         msg.from,
  470.  
  471.         "to",
  472.         msg.to,
  473.  
  474.         "type",
  475.         msg.hdr.type,
  476.  
  477.         "version",
  478.         msg.hdr.version,
  479.  
  480.         "length",
  481.         msg.hdr.length,
  482.  
  483.         "attr",
  484.         msg.hdr.attr,
  485.  
  486.         "auxattr",
  487.         msg.hdr.auxattr,
  488.  
  489.         "netattr",
  490.         msg.hdr.netattr,
  491.  
  492.         "when_written",
  493.         when_written,
  494.  
  495.         "when_imported",
  496.         when_imported,
  497.  
  498.         "number",
  499.         msg.hdr.number,
  500.  
  501.         "thread_orig",
  502.         msg.hdr.thread_orig,
  503.  
  504.         "thread_next",
  505.         msg.hdr.thread_next,
  506.  
  507.         "thread_first",
  508.         msg.hdr.thread_first,
  509.  
  510.         "reserved[16]",
  511.         binstr(msg.hdr.reserved,16),
  512.  
  513.         "offset",
  514.         msg.hdr.offset,
  515.  
  516.         "total_dfields",
  517.         msg.hdr.total_dfields
  518.         );
  519.     for(i=0;i<msg.hdr.total_dfields;i++)
  520.         printf("dfield[%u].type       %02Xh\n"
  521.                "dfield[%u].offset     %lu\n"
  522.                "dfield[%u].length     %d\n"
  523.                ,i,msg.dfield[i].type
  524.                ,i,msg.dfield[i].offset
  525.                ,i,msg.dfield[i].length);
  526.  
  527.     for(i=0;i<msg.total_hfields;i++)
  528.         printf("hfield[%u].type       %02Xh\n"
  529.                "hfield[%u].length     %d\n"
  530.                "hfield[%u]_dat        %s\n"
  531.                ,i,msg.hfield[i].type
  532.                ,i,msg.hfield[i].length
  533.                ,i,binstr(msg.hfield_dat[i],msg.hfield[i].length));
  534.  
  535.     if(msg.from_net.type)
  536.         printf("from_net.type        %02Xh\n"
  537.                "from_net.addr        %s\n"
  538.             ,msg.from_net.type
  539.             ,msg.from_net.type==NET_FIDO
  540.             ? faddrtoa(*(fidoaddr_t *)msg.from_net.addr) : msg.from_net.addr);
  541.  
  542.     if(msg.to_net.type)
  543.         printf("to_net.type          %02Xh\n"
  544.                 "to_net.addr         %s\n"
  545.             ,msg.to_net.type
  546.             ,msg.to_net.type==NET_FIDO
  547.             ? faddrtoa(*(fidoaddr_t *)msg.to_net.addr) : msg.to_net.addr);
  548.  
  549.     if(msg.replyto_net.type)
  550.         printf("replyto_net.type     %02Xh\n"
  551.                "replyto_net.addr     %s\n"
  552.             ,msg.replyto_net.type
  553.             ,msg.replyto_net.type==NET_FIDO
  554.             ? faddrtoa(*(fidoaddr_t *)msg.replyto_net.addr)
  555.                 : msg.replyto_net.addr);
  556.  
  557.     printf("from_agent           %02Xh\n"
  558.            "to_agent             %02Xh\n"
  559.            "replyto_agent        %02Xh\n"
  560.            ,msg.from_agent
  561.            ,msg.to_agent
  562.            ,msg.replyto_agent);
  563.  
  564.     printf("\n");
  565.     smb_freemsgmem(msg);
  566.     l++; }
  567. }
  568.  
  569. /****************************************************************************/
  570. /* Maintain message base - deletes messages older than max age (in days)    */
  571. /* or messages that exceed maximum                                            */
  572. /****************************************************************************/
  573. void maint(void)
  574. {
  575.     int i;
  576.     ulong l,m,n,f,flagged=0;
  577.     time_t now;
  578.     smbstatus_t status;
  579.     smbmsg_t msg;
  580.     idxrec_t huge *idx;
  581.  
  582. printf("Maintaining message base...\r\n");
  583. now=time(NULL);
  584. i=smb_locksmbhdr(10);
  585. if(i) {
  586.     printf("smb_locksmbhdr returned %d\n",i);
  587.     return; }
  588. i=smb_getstatus(&status);
  589. if(i) {
  590.     smb_unlocksmbhdr();
  591.     printf("smb_getstatus returned %d\n",i);
  592.     return; }
  593. if(!status.total_msgs) {
  594.     smb_unlocksmbhdr();
  595.     printf("Empty\n");
  596.     return; }
  597. printf("Loading index...\n");
  598. if((idx=(idxrec_t *)MALLOC(sizeof(idxrec_t)*status.total_msgs))
  599.     ==NULL) {
  600.     smb_unlocksmbhdr();
  601.     printf("can't allocate %lu bytes of memory\n"
  602.         ,sizeof(idxrec_t)*status.total_msgs);
  603.     return; }
  604. fseek(sid_fp,0L,SEEK_SET);
  605. for(l=0;l<status.total_msgs;l++) {
  606.     printf("%lu of %lu\r"
  607.         ,l+1,status.total_msgs);
  608.     if(!fread(&idx[l],1,sizeof(idxrec_t),sid_fp))
  609.         break; }
  610. printf("\nDone.\n\n");
  611.  
  612. if(status.max_age) {
  613.     printf("Scanning for messages more than %u days old...\n"
  614.         ,status.max_age);
  615.     for(m=0;m<l;m++) {
  616.         printf("%lu of %lu (%lu flagged for deletion)\r"
  617.             ,m+1,l,flagged);
  618.         if(idx[m].attr&MSG_PERMANENT)
  619.             continue;
  620.         if((now-idx[m].time)/(24L*60L*60L)>status.max_age) {
  621.             flagged++;
  622.             idx[m].attr|=MSG_DELETE; } }  /* mark for deletion */
  623.     printf("\nDone.\n\n"); }
  624.  
  625. printf("Scanning for read messages to be killed...\n");
  626. for(m=f=0;m<l;m++) {
  627.     printf("%lu of %lu (%lu flagged for deletion)\r"
  628.         ,m+1,l,f);
  629.     if(idx[m].attr&(MSG_PERMANENT|MSG_DELETE))
  630.         continue;
  631.     if((idx[m].attr&(MSG_READ|MSG_KILLREAD))==(MSG_READ|MSG_KILLREAD)) {
  632.         f++;
  633.         flagged++;
  634.         idx[m].attr|=MSG_DELETE; } }
  635. printf("\nDone.\n\n");
  636.  
  637. if(l-flagged>status.max_msgs) {
  638.     printf("Flagging excess messages for deletion...\n");
  639.     for(m=n=0,f=flagged;l-flagged>status.max_msgs && m<l;m++) {
  640.         if(idx[m].attr&(MSG_PERMANENT|MSG_DELETE))
  641.             continue;
  642.         printf("%lu of %lu\r",++n,(l-f)-status.max_msgs);
  643.         flagged++;
  644.         idx[m].attr|=MSG_DELETE; }            /* mark for deletion */
  645.     printf("\nDone.\n\n"); }
  646.  
  647. if(!flagged) {                /* No messages to delete */
  648.     FREE(idx);
  649.     smb_unlocksmbhdr();
  650.     return; }
  651.  
  652. printf("Freeing allocated header and data blocks for deleted messages...\n");
  653. i=smb_open_da(10);
  654. if(i) {
  655.     smb_unlocksmbhdr();
  656.     printf("smb_open_da returned %d\n",i);
  657.     exit(1); }
  658. i=smb_open_ha(10);
  659. if(i) {
  660.     smb_unlocksmbhdr();
  661.     printf("smb_open_ha returned %d\n",i);
  662.     exit(1); }
  663. for(m=n=0;m<l;m++) {
  664.     if(idx[m].attr&MSG_DELETE) {
  665.         printf("%lu of %lu\r",++n,flagged);
  666.         msg.idx=idx[m];
  667.         msg.hdr.number=msg.idx.number;
  668.         if((i=smb_getmsgidx(&msg))!=0) {
  669.             smb_unlockmsghdr(msg);
  670.             printf("\nsmb_getmsgidx returned %d\n",i);
  671.             break; }
  672.         i=smb_lockmsghdr(msg,10);
  673.         if(i) {
  674.             printf("\nsmb_lockmsghdr returned %d\n",i);
  675.             break; }
  676.         if((i=smb_getmsghdr(&msg))!=0) {
  677.             smb_unlockmsghdr(msg);
  678.             printf("\nsmb_getmsghdr returned %d\n",i);
  679.             break; }
  680.         msg.hdr.attr|=MSG_DELETE;            /* mark header as deleted */
  681.         if((i=smb_putmsg(msg))!=0) {
  682.             smb_freemsgmem(msg);
  683.             smb_unlockmsghdr(msg);
  684.             printf("\nsmb_putmsg returned %d\n",i);
  685.             break; }
  686.         smb_unlockmsghdr(msg);
  687.         if((i=smb_freemsg(msg,status))!=0) {
  688.             smb_freemsgmem(msg);
  689.             printf("\nsmb_freemsg returned %d\n",i);
  690.             break; }
  691.         smb_freemsgmem(msg); } }
  692. fclose(sha_fp);
  693. fclose(sda_fp);
  694. printf("\nDone.\n\n");
  695.  
  696. printf("Re-writing index...\n");
  697. rewind(sid_fp);
  698. if(chsize(fileno(sid_fp),0L))
  699.     printf("chsize failed!\n");
  700. for(m=n=0;m<l;m++) {
  701.     if(idx[m].attr&MSG_DELETE)
  702.         continue;
  703.     printf("%lu of %lu\r",++n,l-flagged);
  704.     fwrite(&idx[m],sizeof(idxrec_t),1,sid_fp); }
  705. printf("\nDone.\n\n");
  706.  
  707. FREE(idx);
  708. status.total_msgs-=flagged;
  709. smb_putstatus(status);
  710. smb_unlocksmbhdr();
  711. }
  712.  
  713. /****************************************************************************/
  714. /* Kills 'msgs' number of messags                                           */
  715. /* Returns actual number of messages killed.                                */
  716. /****************************************************************************/
  717. ulong kill(ulong msgs)
  718. {
  719.     int i;
  720.     ulong l,m,n,flagged=0;
  721.     smbstatus_t status;
  722.     smbmsg_t msg;
  723.     idxrec_t *idx;
  724.  
  725. i=smb_locksmbhdr(10);
  726. if(i) {
  727.     printf("smb_locksmbhdr returned %d\n",i);
  728.     return(0); }
  729. i=smb_getstatus(&status);
  730. if(i) {
  731.     smb_unlocksmbhdr();
  732.     printf("smb_getstatus returned %d\n",i);
  733.     return(0); }
  734. printf("Loading index...\n");
  735. if((idx=(idxrec_t *)MALLOC(sizeof(idxrec_t)*status.total_msgs))
  736.     ==NULL) {
  737.     smb_unlocksmbhdr();
  738.     printf("can't allocate %lu bytes of memory\n"
  739.         ,sizeof(idxrec_t)*status.total_msgs);
  740.     return(0); }
  741. fseek(sid_fp,0L,SEEK_SET);
  742. for(l=0;l<status.total_msgs;l++) {
  743.     printf("%lu of %lu\r"
  744.         ,l+1,status.total_msgs);
  745.     if(!fread(&idx[l],1,sizeof(idxrec_t),sid_fp))
  746.         break; }
  747. printf("\nDone.\n\n");
  748.  
  749. printf("Flagging messages for deletion...\n");
  750. for(m=0;m<l && flagged<msgs;m++) {
  751.     if(idx[m].attr&(MSG_PERMANENT))
  752.         continue;
  753.     printf("%lu of %lu\r",++flagged,msgs);
  754.     idx[m].attr|=MSG_DELETE; }            /* mark for deletion */
  755. printf("\nDone.\n\n");
  756.  
  757. printf("Freeing allocated header and data blocks for deleted messages...\n");
  758. i=smb_open_da(10);
  759. if(i) {
  760.     smb_unlocksmbhdr();
  761.     printf("smb_open_da returned %d\n",i);
  762.     exit(1); }
  763. i=smb_open_ha(10);
  764. if(i) {
  765.     smb_unlocksmbhdr();
  766.     printf("smb_open_ha returned %d\n",i);
  767.     exit(1); }
  768. for(m=n=0;m<l;m++) {
  769.     if(idx[m].attr&MSG_DELETE) {
  770.         printf("%lu of %lu\r",++n,flagged);
  771.         msg.idx=idx[m];
  772.         i=smb_lockmsghdr(msg,10);
  773.         if(i) {
  774.             printf("\nsmb_lockmsghdr returned %d\n",i);
  775.             break; }
  776.         msg.hdr.number=msg.idx.number;
  777.         if((i=smb_getmsgidx(&msg))!=0) {
  778.             smb_unlockmsghdr(msg);
  779.             printf("\nsmb_getmsgidx returned %d\n",i);
  780.             break; }
  781.         if((i=smb_getmsghdr(&msg))!=0) {
  782.             smb_unlockmsghdr(msg);
  783.             printf("\nsmb_getmsghdr returned %d\n",i);
  784.             break; }
  785.         msg.hdr.attr|=MSG_DELETE;            /* mark header as deleted */
  786.         if((i=smb_putmsg(msg))!=0) {
  787.             smb_unlockmsghdr(msg);
  788.             printf("\nsmb_putmsg returned %d\n",i);
  789.             break; }
  790.         smb_unlockmsghdr(msg);
  791.         smb_freemsg(msg,status);
  792.         smb_freemsgmem(msg); } }
  793.  
  794. fclose(sha_fp);
  795. fclose(sda_fp);
  796. printf("\nDone.\n\n");
  797.  
  798. printf("Re-writing index...\n");
  799. rewind(sid_fp);
  800. chsize(fileno(sid_fp),0L);
  801. for(m=n=0;m<l;m++) {
  802.     if(idx[m].attr&MSG_DELETE)
  803.         continue;
  804.     printf("%lu of %lu\r",++n,l-flagged);
  805.     fwrite(&idx[m],1,sizeof(idxrec_t),sid_fp); }
  806. printf("\nDone.\n\n");
  807.  
  808. FREE(idx);
  809. status.total_msgs-=flagged;
  810. smb_putstatus(status);
  811. smb_unlocksmbhdr();
  812. return(flagged);
  813. }
  814.  
  815. typedef struct {
  816.     ulong old,new;
  817.     } datoffset_t;
  818.  
  819. /****************************************************************************/
  820. /* Removes all unused blocks from SDT and SHD files                         */
  821. /****************************************************************************/
  822. void packmsgs()
  823. {
  824.     uchar buf[SDT_BLOCK_LEN],ch;
  825.     int i,file;
  826.     ulong l,m,n,datoffsets=0,length,total=0;
  827.     FILE *tmp_sdt,*tmp_shd,*tmp_sid;
  828.     smbhdr_t    hdr;
  829.     smbstatus_t status;
  830.     smbmsg_t    msg;
  831.     datoffset_t *datoffset;
  832.  
  833. printf("Packing message base...\n");
  834. i=smb_locksmbhdr(10);
  835. if(i) {
  836.     printf("smb_locksmbhdr returned %d\n",i);
  837.     return; }
  838. i=smb_getstatus(&status);
  839. if(i) {
  840.     smb_unlocksmbhdr();
  841.     printf("smb_getstatus returned %d\n",i);
  842.     return; }
  843.  
  844. i=smb_open_ha(10);
  845. if(i) {
  846.     smb_unlocksmbhdr();
  847.     printf("smb_open_ha returned %d\n",i);
  848.     return; }
  849. i=smb_open_da(10);
  850. if(i) {
  851.     smb_unlocksmbhdr();
  852.     fclose(sha_fp);
  853.     printf("smb_open_da returned %d\n",i);
  854.     return; }
  855.  
  856. if(!status.total_msgs) {
  857.     printf("Empty\n");
  858.     rewind(shd_fp);
  859.     chsize(fileno(shd_fp),status.header_offset);
  860.     rewind(sdt_fp);
  861.     chsize(fileno(sdt_fp),0L);
  862.     rewind(sid_fp);
  863.     chsize(fileno(sid_fp),0L);
  864.     rewind(sha_fp);
  865.     chsize(fileno(sha_fp),0L);
  866.     rewind(sda_fp);
  867.     chsize(fileno(sda_fp),0L);
  868.     fclose(sha_fp);
  869.     fclose(sda_fp);
  870.     smb_unlocksmbhdr();
  871.     return; }
  872.  
  873.  
  874. if(!(mode&NOANALYSIS)) {
  875.     printf("Analyzing data blocks...\n");
  876.  
  877.     length=filelength(fileno(sda_fp));
  878.  
  879.     fseek(sda_fp,0L,SEEK_SET);
  880.     for(l=m=0;l<length;l+=2) {
  881.         printf("\r%2u%%  ",l ? (long)(100.0/((float)length/l)) : 0);
  882.         i=0;
  883.         if(!fread(&i,2,1,sda_fp))
  884.             break;
  885.         if(!i)
  886.             m++; }
  887.  
  888.     printf("\rAnalyzing header blocks...\n");
  889.  
  890.     length=filelength(fileno(sha_fp));
  891.  
  892.     fseek(sha_fp,0L,SEEK_SET);
  893.     for(l=n=0;l<length;l++) {
  894.         printf("\r%2u%%  ",l ? (long)(100.0/((float)length/l)) : 0);
  895.         ch=0;
  896.         if(!fread(&ch,1,1,sha_fp))
  897.             break;
  898.         if(!ch)
  899.             n++; }
  900.  
  901.     if(!m && !n) {
  902.         printf("\rAlready compressed.\n\n");
  903.         fclose(sha_fp);
  904.         fclose(sda_fp);
  905.         smb_unlocksmbhdr();
  906.         return; }
  907.     printf("\rCompressing %lu data blocks (%lu bytes)\n"
  908.              "        and %lu header blocks (%lu bytes)\n"
  909.               ,m,m*SDT_BLOCK_LEN,n,n*SHD_BLOCK_LEN); }
  910.  
  911. rewind(sha_fp);
  912. chsize(fileno(sha_fp),0L);        /* Reset both allocation tables */
  913. rewind(sda_fp);
  914. chsize(fileno(sda_fp),0L);
  915.  
  916. tmp_sdt=tmpfile();
  917. tmp_shd=tmpfile();
  918. tmp_sid=tmpfile();
  919. if(!tmp_sdt || !tmp_shd || !tmp_sid) {
  920.     smb_unlocksmbhdr();
  921.     fclose(sha_fp);
  922.     fclose(sda_fp);
  923.     printf("error opening temp file\n");
  924.     return; }
  925. setvbuf(tmp_sdt,NULL,_IOFBF,2*1024);
  926. setvbuf(tmp_shd,NULL,_IOFBF,2*1024);
  927. setvbuf(tmp_sid,NULL,_IOFBF,2*1024);
  928. if((datoffset=(datoffset_t *)MALLOC(sizeof(datoffset_t)*status.total_msgs))
  929.     ==NULL) {
  930.     smb_unlocksmbhdr();
  931.     fclose(sha_fp);
  932.     fclose(sda_fp);
  933.     fclose(tmp_sdt);
  934.     fclose(tmp_shd);
  935.     fclose(tmp_sid);
  936.     printf("error allocating mem\n");
  937.     return; }
  938. fseek(shd_fp,0L,SEEK_SET);
  939. fread(&hdr,1,sizeof(smbhdr_t),shd_fp);
  940. fwrite(&hdr,1,sizeof(smbhdr_t),tmp_shd);
  941. fwrite(&status,1,sizeof(smbstatus_t),tmp_shd);
  942. for(l=sizeof(smbhdr_t)+sizeof(smbstatus_t);l<status.header_offset;l++) {
  943.     fread(&ch,1,1,shd_fp);            /* copy additional base header records */
  944.     fwrite(&ch,1,1,tmp_shd); }
  945. fseek(sid_fp,0L,SEEK_SET);
  946. for(l=0;l<status.total_msgs;l++) {
  947.     printf("%lu of %lu\r",l+1,status.total_msgs);
  948.     if(!fread(&msg.idx,1,sizeof(idxrec_t),sid_fp))
  949.         break;
  950.     i=smb_lockmsghdr(msg,10);
  951.     if(i) {
  952.         printf("smb_lockmsghdr returned %d\n",i);
  953.         continue; }
  954.     i=smb_getmsghdr(&msg);
  955.     smb_unlockmsghdr(msg);
  956.     if(i) {
  957.         printf("smb_getmsghdr returned %d\n",i);
  958.         continue; }
  959.     for(m=0;m<datoffsets;m++)
  960.         if(msg.hdr.offset==datoffset[m].old)
  961.             break;
  962.     if(m<datoffsets) {                /* another index pointed to this data */
  963.         printf("duplicate index\n");
  964.         msg.hdr.offset=datoffset[m].new;
  965.         smb_incdat(datoffset[m].new,smb_getmsgdatlen(msg),1); }
  966.     else {
  967.  
  968.         datoffset[datoffsets].old=msg.hdr.offset;
  969.         fseek(sdt_fp,msg.hdr.offset,SEEK_SET);
  970.  
  971.         datoffset[datoffsets].new=msg.hdr.offset
  972.             =smb_fallocdat(smb_getmsgdatlen(msg),1);
  973.         datoffsets++;
  974.  
  975.         /* Actually copy the data */
  976.  
  977.         fseek(tmp_sdt,msg.hdr.offset,SEEK_SET);
  978.         n=smb_datblocks(smb_getmsgdatlen(msg));
  979.         for(m=0;m<n;m++) {
  980.             fread(buf,1,SDT_BLOCK_LEN,sdt_fp);
  981.             fwrite(buf,1,SDT_BLOCK_LEN,tmp_sdt); } }
  982.  
  983.     /* Write the new index entry */
  984.     msg.idx.offset=status.header_offset;
  985.     msg.idx.offset+=smb_fallochdr(smb_getmsghdrlen(msg));
  986.     fwrite(&msg.idx,1,sizeof(idxrec_t),tmp_sid);
  987.  
  988.     /* Write the new header entry */
  989.     fseek(tmp_shd,msg.idx.offset,SEEK_SET);
  990.     fwrite(&msg.hdr,1,sizeof(msghdr_t),tmp_shd);
  991.     for(n=0;n<msg.hdr.total_dfields;n++)
  992.         fwrite(&msg.dfield[n],1,sizeof(dfield_t),tmp_shd);
  993.     for(n=0;n<msg.total_hfields;n++) {
  994.         fwrite(&msg.hfield[n],1,sizeof(hfield_t),tmp_shd);
  995.         fwrite(msg.hfield_dat[n],1,msg.hfield[n].length,tmp_shd); }
  996.     total++;
  997.     smb_freemsgmem(msg); }
  998.  
  999. FREE(datoffset);
  1000. fclose(sha_fp);
  1001. fclose(sda_fp);
  1002.  
  1003. i=smb_trunchdr(10);
  1004. if(i) {
  1005.     printf("smb_trunchdr returned %d\n",i);
  1006.     smb_unlocksmbhdr();
  1007.     fclose(tmp_sdt);
  1008.     fclose(tmp_sid);
  1009.     fclose(tmp_shd);
  1010.     return; }
  1011. rewind(sid_fp);
  1012. chsize(fileno(sid_fp),0L);
  1013. fseek(tmp_sid,0L,SEEK_SET);
  1014. printf("\nCreating new index file...\n");
  1015. for(l=0;l<total;l++) {
  1016.     printf("%lu of %lu\r",l+1,total);
  1017.     if(!fread(&msg.idx,1,sizeof(idxrec_t),tmp_sid))
  1018.         break;
  1019.     if(!fwrite(&msg.idx,1,sizeof(idxrec_t),sid_fp))
  1020.         break; }
  1021.  
  1022. rewind(shd_fp);
  1023. chsize(fileno(shd_fp),0L);
  1024. fseek(tmp_shd,0,SEEK_SET);
  1025. for(l=0;l<status.header_offset;l++) {
  1026.     fread(&ch,1,1,tmp_shd);
  1027.     fwrite(&ch,1,1,shd_fp); }
  1028. printf("\nCreating new header file...\n");
  1029. for(l=0;;l++) {
  1030.     if(!fread(buf,1,SHD_BLOCK_LEN,tmp_shd))
  1031.         break;
  1032.     printf("%lu blocks\r",l+1);
  1033.     if(!fwrite(buf,1,SHD_BLOCK_LEN,shd_fp))
  1034.         break; }
  1035.  
  1036. rewind(sdt_fp);
  1037. chsize(fileno(sdt_fp),0L);
  1038. fseek(tmp_sdt,0L,SEEK_SET);
  1039. printf("\nCreating new data file...\n");
  1040. for(l=0;;l++) {
  1041.     if(!fread(buf,1,SDT_BLOCK_LEN,tmp_sdt))
  1042.         break;
  1043.     printf("%lu blocks\r",l+1);
  1044.     if(!fwrite(buf,1,SDT_BLOCK_LEN,sdt_fp))
  1045.         break; }
  1046. fclose(tmp_sdt);
  1047. fclose(tmp_shd);
  1048. fclose(tmp_sid);
  1049. status.total_msgs=total;
  1050. if((i=smb_putstatus(status))!=0)
  1051.     printf("\nsmb_putstatus returned %d\n",i);
  1052. smb_unlocksmbhdr();
  1053. printf("\nDone.\n\n");
  1054. }
  1055.  
  1056.  
  1057. /****************************************************************************/
  1058. /* Read messages in message base                                            */
  1059. /****************************************************************************/
  1060. void readmsgs(ulong start)
  1061. {
  1062.     char    str[128];
  1063.     int     i,ch,done=0,domsg=1;
  1064.     ulong    l,count;
  1065.     smbmsg_t msg;
  1066.  
  1067. if(start)
  1068.     msg.offset=start-1;
  1069. else
  1070.     msg.offset=0;
  1071. while(!done) {
  1072.     if(domsg) {
  1073.         fseek(sid_fp,msg.offset*sizeof(idxrec_t),SEEK_SET);
  1074.         if(!fread(&msg.idx,1,sizeof(idxrec_t),sid_fp))
  1075.             break;
  1076.         i=smb_lockmsghdr(msg,10);
  1077.         if(i) {
  1078.             printf("smb_lockmsghdr returned %d\n",i);
  1079.             break; }
  1080.         i=smb_getmsghdr(&msg);
  1081.         if(i) {
  1082.             printf("smb_getmsghdr returned %d\n",i);
  1083.             break; }
  1084.  
  1085.         printf("\n%lu (%lu)\n",msg.hdr.number,msg.offset+1);
  1086.         printf("Subj : %s\n",msg.subj);
  1087.         printf("To   : %s",msg.to);
  1088.         if(msg.to_net.type)
  1089.             printf(" (%s)",msg.to_net.type==NET_FIDO
  1090.                 ? faddrtoa(*(fidoaddr_t *)msg.to_net.addr) : msg.to_net.addr);
  1091.         printf("\nFrom : %s",msg.from);
  1092.         if(msg.from_net.type)
  1093.             printf(" (%s)",msg.from_net.type==NET_FIDO
  1094.                 ? faddrtoa(*(fidoaddr_t *)msg.from_net.addr)
  1095.                     : msg.from_net.addr);
  1096.         printf("\nDate : %.24s %s",ctime(&(time_t)msg.hdr.when_written.time)
  1097.             ,zonestr(msg.hdr.when_written.zone));
  1098.         printf("\n\n");
  1099.         for(i=0;i<msg.hdr.total_dfields;i++)
  1100.             switch(msg.dfield[i].type) {
  1101.                 case TEXT_BODY:
  1102.                 case TEXT_TAIL:
  1103.                     fseek(sdt_fp,msg.hdr.offset+msg.dfield[i].offset+2
  1104.                         ,SEEK_SET);
  1105.                     for(l=2;l<msg.dfield[i].length;l++) {
  1106.                         ch=fgetc(sdt_fp);
  1107.                         if(ch)
  1108.                             putchar(ch); }
  1109.                     printf("\n");
  1110.                     break; }
  1111.         i=smb_unlockmsghdr(msg);
  1112.         if(i) {
  1113.             printf("smb_unlockmsghdr returned %d\n",i);
  1114.             break; }
  1115.         smb_freemsgmem(msg); }
  1116.     domsg=1;
  1117.     printf("\nReading %s (?=Menu): ",smb_file);
  1118.     switch(toupper(getch())) {
  1119.         case '?':
  1120.             printf("\n"
  1121.                    "\n"
  1122.                    "(R)e-read current message\n"
  1123.                    "(L)ist messages\n"
  1124.                    "(T)en more titles\n"
  1125.                    "(V)iew message headers\n"
  1126.                    "(Q)uit\n"
  1127.                    "(+/-) Forward/Backward\n"
  1128.                    "\n");
  1129.             domsg=0;
  1130.             break;
  1131.         case 'Q':
  1132.             printf("Quit\n");
  1133.             done=1;
  1134.             break;
  1135.         case 'R':
  1136.             printf("Re-read\n");
  1137.             break;
  1138.         case '-':
  1139.             printf("Backwards\n");
  1140.             if(msg.offset)
  1141.                 msg.offset--;
  1142.             break;
  1143.         case 'T':
  1144.             printf("Ten titles\n");
  1145.             listmsgs(msg.offset+2,10);
  1146.             msg.offset+=10;
  1147.             domsg=0;
  1148.             break;
  1149.         case 'L':
  1150.             printf("List messages\n");
  1151.             listmsgs(1,-1);
  1152.             domsg=0;
  1153.             break;
  1154.         case 'V':
  1155.             printf("View message headers\n");
  1156.             viewmsgs(1,-1);
  1157.             domsg=0;
  1158.             break;
  1159.         case CR:
  1160.         case '+':
  1161.             printf("Next\n");
  1162.             msg.offset++;
  1163.             break; } }
  1164. }
  1165.  
  1166. /***************/
  1167. /* Entry point */
  1168. /***************/
  1169. int main(int argc, char **argv)
  1170. {
  1171.     char cmd[128]="",*p,*s;
  1172.     int i,j,x,y;
  1173.     ulong l;
  1174.     smbstatus_t status;
  1175.  
  1176. smb_file[0]=0;
  1177. printf("\nSynchronet Message Base Utility v%s  "\
  1178.     "Copyright 1994 Digital Dynamics\n\n"
  1179.     ,SMBUTIL_VER);
  1180. for(x=1;x<argc;x++) {
  1181.     if(argv[x][0]=='/') {
  1182.         for(j=1;argv[x][j];j++)
  1183.             switch(toupper(argv[x][j])) {
  1184.                 case 'A':
  1185.                     mode|=NOANALYSIS;
  1186.                     break;
  1187.                 case 'F':   /* file attachment */
  1188.                     mode|=FAST;
  1189.                     break;
  1190.                 case 'D':
  1191.                     mode|=NOCRC;
  1192.                     break;
  1193.                 case 'Z':
  1194.                     if(isdigit(argv[x][j+1]))
  1195.                         tzone=atoi(argv[x]+j+1);
  1196.                     else if(!stricmp(argv[x]+j+1,"EST"))
  1197.                         tzone=EST;
  1198.                     else if(!stricmp(argv[x]+j+1,"EDT"))
  1199.                         tzone=EDT;
  1200.                     else if(!stricmp(argv[x]+j+1,"CST"))
  1201.                         tzone=CST;
  1202.                     else if(!stricmp(argv[x]+j+1,"CDT"))
  1203.                         tzone=CDT;
  1204.                     else if(!stricmp(argv[x]+j+1,"MST"))
  1205.                         tzone=MST;
  1206.                     else if(!stricmp(argv[x]+j+1,"MDT"))
  1207.                         tzone=MDT;
  1208.                     else if(!stricmp(argv[x]+j+1,"PST"))
  1209.                         tzone=PST;
  1210.                     else if(!stricmp(argv[x]+j+1,"PDT"))
  1211.                         tzone=PDT;
  1212.                     j=strlen(argv[x])-1;
  1213.                     break;
  1214.                 default:
  1215.                     printf("\nUnknown opt '%c'\n",argv[x][j]);
  1216.                 case '?':
  1217.                     printf("%s",usage);
  1218.                     exit(1);
  1219.                     break; } }
  1220.     else {
  1221.         if(!cmd[0])
  1222.             strcpy(cmd,argv[x]);
  1223.         else {
  1224.             sprintf(smb_file,"%.64s",argv[x]);
  1225.             p=strrchr(smb_file,'.');
  1226.             s=strrchr(smb_file,'\\');
  1227.             if(p>s) *p=0;
  1228.             strupr(smb_file);
  1229.             printf("Opening %s\r\n",smb_file);
  1230.             if((i=smb_open(10))!=0) {
  1231.                 printf("error %d opening %s message base\n",i,smb_file);
  1232.                 exit(1); }
  1233.             if(!filelength(fileno(shd_fp))) {
  1234.                 printf("Empty\n");
  1235.                 smb_close();
  1236.                 continue; }
  1237.             for(y=0;cmd[y];y++)
  1238.                 switch(toupper(cmd[y])) {
  1239.                     case 'I':
  1240.                         strcpy(filein,cmd+1);
  1241.                         i=smb_locksmbhdr(10);
  1242.                         if(i) {
  1243.                             printf("smb_locksmbhdr returned %d\n",i);
  1244.                             return(1); }
  1245.                         i=smb_getstatus(&status);
  1246.                         if(i) {
  1247.                             printf("smb_getstatus returned %d\n",i);
  1248.                             return(1); }
  1249.                             smb_unlocksmbhdr();
  1250.                         postmsg(status);
  1251.                         y+=strlen(cmd)-1;
  1252.                         break;
  1253.                     case 'K':
  1254.                         printf("Killing %lu messages...\n",atol(cmd+1));
  1255.                         l=kill(atol(cmd+1));
  1256.                         printf("%lu messages killed.\n",l);
  1257.                         y+=strlen(cmd)-1;
  1258.                         break;
  1259.                     case 'S':
  1260.                         showstatus();
  1261.                         break;
  1262.                     case 'C':
  1263.                         config();
  1264.                         break;
  1265.                     case 'L':
  1266.                         listmsgs(atol(cmd+1),-1L);
  1267.                         y+=strlen(cmd)-1;
  1268.                         break;
  1269.                     case 'P':
  1270.                         packmsgs();
  1271.                         break;
  1272.                     case 'R':
  1273.                         readmsgs(atol(cmd+1));
  1274.                         y+=strlen(cmd)-1;
  1275.                         break;
  1276.                     case 'V':
  1277.                         viewmsgs(atol(cmd+1),-1L);
  1278.                         y+=strlen(cmd)-1;
  1279.                         break;
  1280.                     case 'M':
  1281.                         maint();
  1282.                         break;
  1283.                     default:
  1284.                         printf("%s",usage);
  1285.                         break; }
  1286.             smb_close(); } } }
  1287. if(!cmd[0])
  1288.     printf("%s",usage);
  1289. return(0);
  1290. }
  1291.